#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>





	   
// https://blog.csdn.net/dreams_deng/article/details/104114489



/**
  * 参考 例子进度条
*/
void progress_bar(void){    


#if 0
//写死了
   int i = 0;    
   char value[3]={0};
   for (i = 0 ; i < 2 ; i++) {  
      //printf格式控制时默认右对齐，所以要在前面加-变成左对齐    
	  // i可以理解为100块，每次read的快数 
      value[i] = '#';  
      printf("[%-2s] [%d%%]\r", value, i);                                                                                                                                  
      fflush(stdout);//刷新屏幕打印  
      usleep(1*1000*1000);//休眠100000微秒

   }  
#endif 



// # 是动态的
#if 0 
   int block = 100 ;
   char *p = malloc(block+1);
   memset(p, '\0', block+1);    

  for (int i = 0 ; i < block ; i++) {  
      p[i] = '#';  
	  p[i+1] = '\0';  
   //   printf("[%-2s] [%d%%]\r", p, i);      
      printf("[%*s] [%d%%]\r", -block, p, (i+1)*100/block);  // 进度百分比也修正为更合理的计算方式                                                                                                                            
      fflush(stdout);//刷新屏幕打印  
      usleep(1*100*1000);//休眠100000微秒

  }
   free(p);
   printf("\n");  
#endif 


//如果block是 312 
   int block_size = 400 ;
   float block_size_ratio =  block_size / 100.0 ; // 3.12 
   int cnt = 1;
   int block = 100 ;
   char *p = malloc(block+1);
   memset(p, '\0', block+1);    
   int i = 0;
while(cnt <= block_size){
 
	//执行一次，读取一块完成
   if( cnt % (int)ceil(block_size_ratio) == 0 ) {  // 3.12 向上取整 4
     if(i<100){
        p[i] = '#';  
	    p[i+1] = '\0'; 
	    printf("[%*s] [%d%%]\r", -block, p, (i+1)*100/block);  // 进度百分比也修正为更合理的计算方式                                                                                                                            
        fflush(stdout);//刷新屏幕打印  
        usleep(1*100*1000);//休眠100000微秒 
	    i++; 
     }

	 //剩下部分一次性打印完毕
     if( (block_size / (int)ceil(block_size_ratio)== i)  &&  (cnt= block_size ) ) { 
          for(int j=i;j<100;j++) {
			      p[j] = '#';  
	              p[j+1] = '\0'; 
				  printf("[%*s] [%d%%]\r", -block, p, (j+1)*100/block);
				  fflush(stdout);//刷新屏幕打印  
                  usleep(1*100*1000);//休眠100000微秒 
				  
				  
				 
		  }
	 }
	      printf("%d - %d \r ",cnt, i);
  }
       cnt++;
 } 
   free(p);
   printf("\n");   
   
}                                                           


// ctrl+d 理解 就是文本结束,是一个特殊字符， 就是上面read读取结束返回的0 
/***
 * 测试1:
 *robin@robin-vm:~/share/linux-api/02_file$ ./a.exe 
abc  + 输入Enter 
ret=4 
  输入abc 输入Enter , ret=4 , 包括Enter 
  测试2:
  robin@robin-vm:~/share/linux-api/02_file$ ./a.exe 
123ret=3
  输入123 输入ctrl+d , ret=3,  证明上面
 *
 */
#define SIZE 5
void test01(){
		int ret;
	char buf[SIZE];
	bzero(buf, SIZE);
	
	ret = read(STDIN_FILENO, buf, SIZE);

	printf("ret=%d\n", ret);

	write(STDOUT_FILENO, buf, SIZE);
}


//作业1： 
//使用read, write拷贝文件问题，一次读取5个字节，最后一次可能不足5个字节， 
// 写入的字节必须是实际读取的字节数
//   并且实现进度条
void test02(int argc, char *argv[]){
	int ret;
	int fd, fdw;
	char buf[SIZE];
	
	if (argc != 3) {
		printf("Usage:\n %s src des\n", argv[0]);
		_exit(1);
	}
	fd = open(argv[1], O_RDONLY);
    
    lseek(fd,0,SEEK_SET);
	// 2.通过lseek获取文件大小
	long file_size=lseek(fd,0,SEEK_END);
   // printf("filesize：  %ld B\n",file_size);
	int block_size=  (int ) ceil( file_size / (SIZE*1.0)) ;  
	printf("filesize：  %ld  - block_size = %d \n",file_size,block_size);

	
	lseek(fd,0,SEEK_SET); //重新定位到文件开始位置
	
    int size_ = 100 ;
	char* value = (char*)malloc(size_+1);
	memset(value, '\0', size_+1);
    int block_num = 0;
    int cnt = 1;
	float block_size_ratio =  block_size / 100.0 ; //  8.41
 
	if (fd == -1) {
		perror("open fail1 \n");
		_exit(1); //退出进程
	}
	fdw = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0664); 
	if (fd == -1) {
		perror("open fail2 \n"); 
		_exit(1); //退出进程
	}
	// printf("fd = %d\n", fd);
   
	while (1) {
		ret = read(fd, buf, SIZE);
		if (ret < 0) {
			perror("read");
			_exit(1);
		} else if (ret == 0) {  //读到文件末尾
			// printf("read file over\n");
			break;
		} else {
		
		//	printf("ret=%d\n", ret);
			write(fdw, buf, ret); //写入实际读到的字节数

		

          if( cnt % (int)ceil(block_size_ratio) == 0 ) {  // 3.12 向上取整 4
             if(block_num<100){
       				value[block_num] = '#';  
	    			value[block_num+1] = '\0'; 
	                printf("[%*s] [%d%%]\r", -size_, value, (block_num+1)*100/size_);  // 进度百分比也修正为更合理的计算方式                                                                                                                            
                    fflush(stdout);//刷新屏幕打印  
                    usleep(1*100*1000);//休眠100000微秒 
	                block_num++; 
               }
		  }

		   //剩下部分一次性打印完毕
     if(   cnt == block_size) { 
          for(int j=block_num;j<100;j++) {

			      value[j] = '#';  
	              value[j+1] = '\0'; 
				  printf("[%*s] [%d%%]\r", -size_, value, (j+1)*100/size_);
				  fflush(stdout);//刷新屏幕打印  
                  usleep(1*100*1000);//休眠100000微秒 
		  }
		//   	printf("%d - %d \n ",cnt, block_num);
	    }
    //	printf("%d - %d  -%d  \n ",cnt, block_num, block_size);
	    	
		    cnt++;
     }
		
	}


    free(value);
	close(fdw);
	close(fd);

    printf("\n");
}


// 作业2： 读取串口包
/*
robin@robin-vm:~/share/linux-api/02_file/data$ hexdump -C  uart_data.dat 
00000000  23 23 49 44 54 48 01 03  12 00 20 65 00 23 23 49  |##IDTH.... e.##I|
00000010  44 54 48 01 03 12 00 20  65 00 23 23 49 44 54 48  |DTH.... e.##IDTH|
00000020  01 03 12 00 20 65 00 23  23 49 44 54 48 01 03 12  |.... e.##IDTH...|
00000030  00 21 65 00 23 23 49 44  54 48 01 03 12 00 21 65  |.!e.##IDTH....!e|
00000040  00 23 23 49 44 54 48 01  03 12 00 21 66 00 23 23  |.##IDTH....!f.##|
00000050  49 44 54 48 01 03 12 00  21 66 00 23 23 49 44 54  |IDTH....!f.##IDT|
00000060  48 01 03 12 00 21 66 00  23 23 49 44 54 48 01 03  |H....!f.##IDTH..|
00000070  12 00 21 66 00 23 23 49  44 54 48 01 03 12 00 21  |..!f.##IDTH....!|
00000080  66 00                                             |f.|
00000082
  上面模拟串口数据, 一个包13个字节， 
          头部6个字节  ##IDTH   节点号    温度         湿度       关照    
  00000000  23 23 49 44 54 48   01       03   12     00 20      65 00     |##IDTH.... e.|

  如果中途打开UART，uart 已经在发送数据了，丢弃 用lseek模拟一下
*/

int  check_data(int fd,char check,int ischeck,char* data ){
  	char buf[2] ={0};
	int ret = -1;
    ret = read(fd, buf, 1);
	//printf("ret=%d  buf[0]=%c \n",ret,buf[0]);
	   if(ret < 0) {
		  perror("read err");
		  _exit(-1);
	   } else if(ret == 0) {
		  printf("file end\n");
		  //从头开始读
		//  lseek(fd,0,SEEK_SET);  
		   _exit(-1);
	   } else if(ret == 1) {
		  //正常读取13个字节
	
		  if(  ischeck ==1  &&  (buf[0] ==  check ) ) {
			
              return 1; 
		  }else {
			 *data = buf[0];
		  }
	   }
	   return 0; 
}

void test03(int argc, char *argv[]) {
	int fd1 = -1;	
    fd1 = open("./data/uart_data.dat", O_RDWR); 
   	if (-1 == fd1)	
	{
		perror("文件打开错误");
		_exit(-1);
	}
	else
	{
	}
    lseek(fd1,5,SEEK_SET); //模拟中途打开，丢弃后面13-5

	int ret = -1 ;
	char data = '\0';
	char data_buf[7]={0};

	while(1) {
		//##IDTH 
		  	if ( check_data(fd1,'#',1,&data) == 1 ) {
				     usleep(50*1000); //模拟串口数据间隔
					// putchar('1');
					  if ( check_data(fd1,'#',1,&data) == 1 ) {
                           usleep(50*1000);
						//    putchar('2');
						     if ( check_data(fd1,'I',1,&data) == 1 ) {
								    usleep(50*1000);
								//	 putchar('3');
									if ( check_data(fd1,'D',1,&data) == 1 ) {
									      usleep(50*1000);
										//   putchar('4');
										  if ( check_data(fd1,'T',1,&data) == 1 ) {
											      usleep(50*1000);
												   //      putchar('5');
									               		 if ( check_data(fd1,'H',1,&data) == 1 ) {
															//   putchar('6');
														for(int i=0;i<7;i++) {
														    data= '\0';
															check_data(fd1,0,0,&data); 
															data_buf[i] = data; //节点号
															usleep(50*1000); 
												         }
														 printf("node=%02x temp=%02x humi=%02x light=%02x\n",data_buf[0],data_buf[2],data_buf[4],data_buf[5]);
							 }
	                   }
	        }
		}
	  }
	}
 }
    close(fd1);
}


int main(int argc, char *argv[]){

   //  main01();

   //    test01();
   //  progress_bar();
    //   test02(argc,argv);

        test03(argc,argv);
  //   progress_bar();

   return 0; 
}

